home *** CD-ROM | disk | FTP | other *** search
/ Future Workshop / Future Workshop.iso / multimed / qtw111 / pviewer / pictkids.c < prev    next >
C/C++ Source or Header  |  1994-01-11  |  49KB  |  1,314 lines

  1.  
  2. // ---------------------------------------------------------------------
  3. //
  4. // PictKids.c - Picture Viewer - QuickTime for Windows
  5. //
  6. //              Version 1.0
  7. //
  8. //              (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
  9. //
  10. // ---------------------------------------------------------------------
  11.  
  12.  
  13. // Includes
  14. // --------
  15. #define NOMINMAX
  16. #include <Windows.H> // Required by Windows
  17. #include <stdlib.h>  // Required for abs function
  18.  
  19. #include <qtole.h>  // Interface to qtole dll
  20. #include <qtw.h>    // Interface to QuickTime
  21. #include "common.h" // Interface to common.c
  22.  
  23. #include "viewer.h"  // Interface to *.c files
  24. #include "viewer.hr" // Defines used in *.rc files
  25. #include "picture.h" // Interface to picture window
  26.                      // child window processing
  27.  
  28.  
  29. // Constants
  30. // -----------------------
  31. #define BANNER_TEXT_HEIGHT      9 // Banner text height in points
  32. #define TEXT_EXTRA_SPACING      1 // Extra spacing in number text
  33.  
  34. // Message-Persistent Data
  35. // -----------------------
  36. static struct // Hungarian notation: g
  37.   {WORD        wScrollBarWidth;     // Vertical scroll bar width
  38.    WORD        wScrollBarHeight;    // Horizontal scroll bar height
  39.    WORD        wBannerBarHeight;    // Banner bar height
  40.    WORD        wZoomWndWidth;       // Width of zoom scroll bar window
  41.    WORD        wMinWndHeight;       // Minimum height of window
  42.    HBITMAP     hbmpGrowBox;         // Grow box bitmap
  43.    BOOL        bLimitGrowBoxResize; // Flag to turn on max resize limits
  44.                                     // using grow box
  45.    POINT       ptMaxGrowBoxResize;  // Max size for grow box resizing
  46.  
  47.    RECT        rcResizeRect;   // Maximized wnd grow box resize rect
  48.    POINT       ptCursorOffset; // Offset of cursor from edge of window
  49.                                // used during maximized wnd grow box resize
  50.   } g;
  51.  
  52.  
  53. // Exported callback function
  54. // ----------------------------
  55. LONG __export CALLBACK PictureBannerWndProc  (HWND, UINT, WPARAM, LPARAM);
  56.  
  57. // Internal Function Declarations
  58. // ------------------------------
  59. static VOID    NEAR UpdateScrollingParms    (HWND, NPPICTUREDATA, LPRECT);
  60. static HBITMAP NEAR GetGrowBoxBitmap        (HDC, NPPICTUREDATA);
  61. static VOID    NEAR DrawTheFrameRect        (LPRECT);
  62.  
  63.  
  64. // Function: ResizeKids - Resizes the child windows whenever the picture
  65. //                        window is resized
  66. // --------------------------------------------------------------------
  67. // Parameters: HWND    hwndPicture       Handle of picture window
  68. //             WORD    wClientWidth      Width of client rect
  69. //             WORD    wClientHeight     Height of client rect
  70. //
  71. // Returns:    0L
  72. // --------------------------------------------------------------------
  73. VOID FAR ResizeKids
  74.     ( HWND hwndPicture, WORD wClientWidth, WORD wClientHeight )
  75.  
  76. {
  77.     NPPICTUREDATA   pPictureData; // -> picture data struct
  78.     RECT            rcPicture;    // Picture rect in picture coordinates
  79.     HDWP            hdwp;         // Handle to defer wnd pos struct
  80.     int             xBrdr;        // Width of non resizable border
  81.     int             yBrdr;        // Height of non resizable border
  82.  
  83.     // Note: All the extra terms involving xBrdr and yBrdr are used to make
  84.     // the control boundaries match up correctly without heavy lines 
  85.     // appearing between the controls
  86.  
  87.     xBrdr = GetSystemMetrics( SM_CXBORDER );
  88.     yBrdr = GetSystemMetrics( SM_CYBORDER );
  89.  
  90.     if( !(pPictureData =
  91.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  92.         CommonTellUser( ViewerQueryResources(),
  93.             VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  94.         return;
  95.     }
  96.  
  97.     if( ( hdwp = BeginDeferWindowPos( 5 )) &&
  98.         // Zoom window. This control has a constant size
  99.         ( hdwp = DeferWindowPos( hdwp, pPictureData->zsZoomScroll.hwnd,
  100.         NULL,
  101.         -xBrdr,
  102.         wClientHeight - g.wScrollBarHeight + yBrdr,
  103.         g.wZoomWndWidth,
  104.         g.wScrollBarHeight, 
  105.         SWP_NOZORDER )) &&
  106.         // Banner bar. This control has a constant height
  107.         ( hdwp = DeferWindowPos( hdwp, pPictureData->hwndBanner, 
  108.         NULL,
  109.         0,
  110.         0,
  111.         wClientWidth,
  112.         g.wBannerBarHeight,
  113.         SWP_NOZORDER )) && 
  114.         // Vertical scroll bar. This control has a constant width
  115.         ( hdwp = DeferWindowPos( hdwp, pPictureData->spmsVScroll.hwnd,
  116.         NULL, 
  117.         wClientWidth - g.wScrollBarWidth + xBrdr,
  118.         g.wBannerBarHeight - yBrdr,
  119.         g.wScrollBarWidth,
  120.         wClientHeight - g.wScrollBarHeight
  121.         - g.wBannerBarHeight + 3 * yBrdr,
  122.         SWP_NOZORDER )) && 
  123.         // Horizontal scroll bar. This control has a constant height
  124.         ( hdwp = DeferWindowPos( hdwp, pPictureData->spmsHScroll.hwnd,
  125.         NULL, 
  126.         g.wZoomWndWidth - 2 * xBrdr,
  127.         wClientHeight - g.wScrollBarHeight + yBrdr,
  128.         wClientWidth - g.wZoomWndWidth - 
  129.         g.wScrollBarWidth + 4 * xBrdr,
  130.         g.wScrollBarHeight,
  131.         SWP_NOZORDER ))) {
  132.         EndDeferWindowPos( hdwp );
  133.     } 
  134.     else { // Zoom window. This control has a constant size
  135.         MoveWindow( pPictureData->zsZoomScroll.hwnd,
  136.             -xBrdr, wClientHeight - g.wScrollBarHeight + yBrdr,
  137.             g.wZoomWndWidth, g.wScrollBarHeight, TRUE );
  138.  
  139.         // Banner bar. This control has a constant height
  140.         MoveWindow( pPictureData->hwndBanner, 0, 0,
  141.             wClientWidth, g.wBannerBarHeight, TRUE );
  142.  
  143.         // Vertical scroll bar. This control has a constant width
  144.         MoveWindow( pPictureData->spmsVScroll.hwnd,
  145.             wClientWidth - g.wScrollBarWidth + xBrdr,
  146.             g.wBannerBarHeight - yBrdr, g.wScrollBarWidth,
  147.             wClientHeight - g.wScrollBarHeight -
  148.             g.wBannerBarHeight + 3 * yBrdr, TRUE );
  149.  
  150.         // Horizontal scroll bar. This control has a constant height
  151.         MoveWindow( pPictureData->spmsHScroll.hwnd,
  152.             g.wZoomWndWidth - 2 * xBrdr,
  153.             wClientHeight - g.wScrollBarHeight + yBrdr,
  154.             wClientWidth - g.wZoomWndWidth -
  155.             g.wScrollBarWidth + 4 * xBrdr,
  156.             g.wScrollBarHeight, TRUE );
  157.     }
  158.  
  159.     pPictureData->rcGrowBox.left = wClientWidth  - 
  160.         g.wScrollBarWidth + 2 * xBrdr;
  161.     pPictureData->rcGrowBox.top  = wClientHeight -
  162.         g.wScrollBarHeight + 2 * yBrdr;
  163.     pPictureData->rcGrowBox.right  = wClientWidth;
  164.     pPictureData->rcGrowBox.bottom = wClientHeight;
  165.  
  166.     rcPicture.left   = rcPicture.top = 0;
  167.     rcPicture.right  = wClientWidth;
  168.     rcPicture.bottom = wClientHeight;
  169.     PictureRectFromClient( &rcPicture );
  170.  
  171.     UpdateScrollingParms( hwndPicture, pPictureData, &rcPicture );
  172.  
  173.     // Force these to get painted now to avoid long delay while
  174.     // waiting for the picture to be painted. This improves the 
  175.     // appearance of the window during resizing
  176.     UpdateWindow( pPictureData->zsZoomScroll.hwnd );
  177.     UpdateWindow( pPictureData->hwndBanner );
  178.     UpdateWindow( pPictureData->spmsHScroll.hwnd );
  179.     UpdateWindow( pPictureData->spmsVScroll.hwnd );
  180.  
  181.     return;
  182. }
  183.  
  184.  
  185. // Function: CreateViewerKids - Creates the child windows for the picture
  186. //                              window
  187. // --------------------------------------------------------------------
  188. // Parameters: HWND           hwndPicture     Handle of picture window
  189. //             NPPICTUREDATA  pPictureData    -> to picture data struct
  190. //
  191. // Returns:    LONG           0l if OK
  192. // --------------------------------------------------------------------
  193. LONG FAR CreateViewerKids( HWND hwndPicture, NPPICTUREDATA pPictureData )
  194.  
  195. {
  196.     WORD    wIDError; // Resource error string id
  197.  
  198.     g.wScrollBarWidth  = (WORD) GetSystemMetrics( SM_CXVSCROLL );
  199.     g.wScrollBarHeight = (WORD) GetSystemMetrics( SM_CYHSCROLL );
  200.     g.wBannerBarHeight = (WORD) GetSystemMetrics( SM_CYMENU );
  201.     g.wMinWndHeight    = (WORD) ( GetSystemMetrics( SM_CYCAPTION ) +
  202.         g.wBannerBarHeight + g.wScrollBarHeight + 
  203.         3 * GetSystemMetrics( SM_CYVSCROLL ));
  204.  
  205.  
  206.     wIDError = VIEWER_STRING_NOMEMORY;
  207.     if( !( pPictureData->spmsHScroll.hwnd =
  208.         CreateWindow( "scrollbar", NULL,
  209.         WS_CHILD | WS_VISIBLE | SBS_HORZ,
  210.         0, 0, 0, 0, hwndPicture,
  211.         (HMENU) PICTURE_HORZ_SCROLL,
  212.         ViewerQueryInstance(), NULL ))) {
  213.         goto Failed;
  214.     }
  215.  
  216.     if( !(pPictureData->spmsVScroll.hwnd =
  217.         CreateWindow( "scrollbar", NULL,
  218.         WS_CHILD | WS_VISIBLE | SBS_VERT,
  219.         0, 0, 0, 0, hwndPicture,
  220.         (HMENU) PICTURE_VERT_SCROLL,
  221.         ViewerQueryInstance(), NULL ))) {
  222.         goto Failed;
  223.     }
  224.  
  225.     // Try initial width. This may be adjusted during create processing
  226.     if( !( pPictureData->zsZoomScroll.hwnd =
  227.         CreateWindow( PICTURE_ZOOM_CLASS, NULL,
  228.         WS_CHILD | WS_VISIBLE | WS_BORDER,
  229.         0, 0, 6 * GetSystemMetrics( SM_CXHSCROLL ),
  230.         g.wScrollBarHeight, hwndPicture,
  231.         (HMENU) PICTURE_ZOOM_SCROLL,
  232.         ViewerQueryInstance(), NULL ))) {
  233.         goto Failed;
  234.     }
  235.     else // Set the global variable here because dimensions may have
  236.          // been adjusted. Use the query because GetClientRect() won't 
  237.          // work until after first call to MoveWindow() and we need 
  238.          // width before then.
  239.     {
  240.         g.wZoomWndWidth = ViewerQueryZoomWndWidth();
  241.     }
  242.  
  243.     if( !( pPictureData->hwndBanner =
  244.         CreateWindow( PICTURE_BANNER_CLASS, NULL,
  245.         WS_CHILD | WS_VISIBLE,
  246.         0, 0, 0, 0, hwndPicture,
  247.         (HMENU) PICTURE_BANNER,
  248.         ViewerQueryInstance(), NULL ))) {
  249.         goto Failed;
  250.     }
  251.     // this window does nothing so disable it
  252.     EnableWindow( pPictureData->hwndBanner, FALSE );
  253.  
  254.     return 0L;
  255.  
  256.  Failed:
  257.     CommonTellUser( ViewerQueryResources(), wIDError, NULL, MB_OK );
  258.     return MAKELONG( wIDError, 0 );
  259. }
  260.  
  261.  
  262. // Function: ZoomPicture - Resizes the Picture to the input width and
  263. //                         height
  264. // --------------------------------------------------------------------
  265. // Parameters: HWND         hwndPicture     Handle of Picture window
  266. //             WORD         wZoomIndex      Index of desired zoom
  267. //
  268. // Returns:    LONG         0L if successful
  269. // --------------------------------------------------------------------
  270. LONG FAR ZoomPicture( HWND hwndPicture, WORD wZoomIndex )
  271.  
  272. {
  273.     NPPICTUREDATA  pPictureData; // -> picture data struct
  274.     RECT           rcMaxPicture; // Current max picture display area
  275.     WORD           wZoomMult;    // Zoom multiplier factor
  276.  
  277.  
  278.     if( !(pPictureData =
  279.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  280.         CommonTellUser( ViewerQueryResources(),
  281.             VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  282.         return VIEWER_STRING_NOPICDATA;
  283.     }
  284.  
  285.     if( pPictureData->zsZoomScroll.wCurZoomIndex == wZoomIndex )
  286.         return 0L;
  287.  
  288.     pPictureData->rcCurPictureRect.left = 0;
  289.     pPictureData->rcCurPictureRect.top  = 0;
  290.  
  291.     wZoomMult = ViewerQueryZoomMultiplier( wZoomIndex );
  292.     pPictureData->rcCurPictureRect.right = 
  293.         MulDiv( pPictureData->idImageInfo.width, wZoomMult, 100 );
  294.     pPictureData->rcCurPictureRect.bottom = 
  295.         MulDiv( pPictureData->idImageInfo.height, wZoomMult, 100 );
  296.  
  297.     // Get client rect
  298.     GetClientRect( hwndPicture, &rcMaxPicture );
  299.  
  300.     // Convert to Picture coordinates
  301.     PictureRectFromClient( &rcMaxPicture );
  302.  
  303.     // This routine also offsets rcCurPictureRect when necessary
  304.     UpdateScrollingParms( hwndPicture, pPictureData, &rcMaxPicture );
  305.  
  306.     // Update buckle ...
  307.     pPictureData->zsZoomScroll.wCurZoomIndex = wZoomIndex;
  308.     if( IsWindowVisible( pPictureData->zsZoomScroll.hwnd ))
  309.         SendMessage( pPictureData->zsZoomScroll.hwnd,
  310.         WM_ZOOM_MOVEBUCKLE, (WPARAM) wZoomIndex, 0L );
  311.  
  312.     // ... and paint
  313.     InvalidateRect( hwndPicture, NULL, TRUE);
  314.  
  315.     if( pPictureData->hwndGetInfo )
  316.         SendMessage( pPictureData->hwndGetInfo,
  317.         WM_INFO_CURRENTSIZE, 0, 0L );
  318.  
  319.     return 0L;
  320. }
  321.  
  322.  
  323. // Function: ClientRectFromPicture - Returns the client rect in client
  324. //                                   coordinates that corresponds to the
  325. //                                   input picture rect in picture coords.
  326. // --------------------------------------------------------------------
  327. // Parameters: LPRECT       lprc     -> Picture rect on input
  328. //
  329. // Returns:    VOID         lprc     -> Client rect on output
  330. // --------------------------------------------------------------------
  331. VOID FAR ClientRectFromPicture( LPRECT lprc )
  332.  
  333. {
  334.     lprc->right  -= lprc->left;
  335.     lprc->bottom -= lprc->top;
  336.     lprc->left = lprc->top = 0;
  337.  
  338.     lprc->right  += g.wScrollBarWidth - 
  339.         GetSystemMetrics( SM_CXBORDER );
  340.     lprc->bottom += g.wScrollBarHeight + g.wBannerBarHeight -
  341.         GetSystemMetrics( SM_CYBORDER );
  342.  
  343.     return;
  344. }
  345.  
  346. // Function: PictureRectFromClient - Returns the maximum picture rect
  347. //                                   in picture coordinates corresponding
  348. //                                   to the input client rect in
  349. //                                   client coords
  350. // --------------------------------------------------------------------
  351. // Parameters: LPRECT       lprc   -> Client rect on input
  352. //
  353. // Returns:    VOID         lprc   -> Max Picture rect on output
  354. // --------------------------------------------------------------------
  355. VOID FAR PictureRectFromClient( LPRECT lprc )
  356.  
  357. {
  358.     lprc->right  -= lprc->left;
  359.     lprc->bottom -= lprc->top;
  360.  
  361.     lprc->left = lprc->top = 0;
  362.     lprc->right  -= g.wScrollBarWidth - 
  363.         GetSystemMetrics( SM_CXBORDER );
  364.     lprc->bottom -= g.wScrollBarHeight + g.wBannerBarHeight -
  365.         GetSystemMetrics( SM_CYBORDER );
  366.  
  367.     return;
  368. }
  369.  
  370. // Function: ClientToPicture - Converts from client to picture coordinates
  371. // --------------------------------------------------------------------
  372. // Parameters: LPPOINT       lppt     -> points
  373. //             WORD          wNum     Number of points to convert
  374. //
  375. // Returns:    VOID
  376. // --------------------------------------------------------------------
  377. VOID FAR ClientToPicture( LPPOINT lppt, WORD wNum )
  378.  
  379. {
  380.     WORD    i; // Counter
  381.  
  382.     for(i=0; i < wNum; i++, lppt++)
  383.         lppt->y -= g.wBannerBarHeight;
  384.  
  385.     return;
  386. }
  387.  
  388. // Function: PictureToClient - Converts from picture to client coordinates
  389. // --------------------------------------------------------------------
  390. // Parameters: LPPOINT       lppt     -> points
  391. //             WORD          wNum     number of points to convert
  392. //
  393. // Returns:    VOID
  394. // --------------------------------------------------------------------
  395. VOID FAR PictureToClient( LPPOINT lppt, WORD wNum )
  396.  
  397. {
  398.     WORD    i; // Counter
  399.  
  400.     for(i=0; i < wNum; i++, lppt++)
  401.         lppt->y += g.wBannerBarHeight;
  402.  
  403.     return;
  404. }
  405.  
  406. // Function: SetMinMaxInfo - Processes the picture window
  407. //                           WM_GETMINMAXINFO message
  408. // --------------------------------------------------------------------
  409. // Parameters: MINMAXINFO FAR*    lpmmi   -> to minmaxinfo struct
  410. //
  411. // Returns:    LONG               always 0L
  412. // --------------------------------------------------------------------
  413. LONG FAR SetMinMaxInfo( MINMAXINFO FAR* lpmmi )
  414.  
  415. {
  416.     lpmmi->ptMinTrackSize.x = g.wZoomWndWidth +
  417.         5 * GetSystemMetrics( SM_CXHSCROLL );
  418.     lpmmi->ptMinTrackSize.y = g.wMinWndHeight;
  419.  
  420.     if( g.bLimitGrowBoxResize ) {
  421.         lpmmi->ptMaxTrackSize = g.ptMaxGrowBoxResize;
  422.     }
  423.  
  424.     return 0L;
  425. }
  426.  
  427.  
  428. // Function: UpdateScrollingParms - Update the scroll bar parameters after
  429. //                                  size of picture is changed
  430. // --------------------------------------------------------------------
  431. // Parameters: HWND           hwndPicture      Handle of picture window
  432. //             NPPICTUREDATA  pPictureData     -> picture data struct
  433. //             LPRECT         lprcMaxPicture   -> to to picture display
  434. //                                             area of wnd
  435. //
  436. // Returns:    VOID
  437. // --------------------------------------------------------------------
  438. static VOID NEAR UpdateScrollingParms( HWND hwndPicture,
  439.                     NPPICTUREDATA pPictureData, LPRECT lprcMaxPicture )
  440.  
  441. {
  442.     WORD      wCurPictWidth;  // Current picture width
  443.     WORD      wCurPictHeight; // Current picture height
  444.     WORD      wOldMax;        // Previous max scroll value
  445.     WORD      wDisplayWidth;  // Display width, i.e. area available
  446.                               // for display of picture
  447.     WORD      wDisplayHeight; // Display height
  448.  
  449.  
  450.     wCurPictWidth  = pPictureData->rcCurPictureRect.right -
  451.         pPictureData->rcCurPictureRect.left;
  452.     wCurPictHeight = pPictureData->rcCurPictureRect.bottom -
  453.         pPictureData->rcCurPictureRect.top;
  454.     wDisplayWidth  = lprcMaxPicture->right - lprcMaxPicture->left;
  455.     wDisplayHeight = lprcMaxPicture->bottom - lprcMaxPicture->top;
  456.  
  457.     // leave these fixed
  458.     pPictureData->spmsHScroll.wCurLine = g.wScrollBarWidth;
  459.     pPictureData->spmsVScroll.wCurLine = g.wScrollBarHeight;
  460.  
  461.     // Adjust these for size of window
  462.     pPictureData->spmsHScroll.wCurPage = wDisplayWidth - 1;
  463.     pPictureData->spmsVScroll.wCurPage = wDisplayHeight - 1;
  464.  
  465.     // Set horizontal scrollbar parms
  466.     if( wDisplayWidth >= wCurPictWidth ) {
  467.         pPictureData->spmsHScroll.wCurPos  = 0;
  468.         pPictureData->spmsHScroll.wCurMax  = 0;
  469.         EnableWindow( pPictureData->spmsHScroll.hwnd, FALSE );
  470.     }
  471.     else {
  472.         wOldMax = pPictureData->spmsHScroll.wCurMax;
  473.         pPictureData->spmsHScroll.wCurMax  =
  474.             wCurPictWidth - wDisplayWidth;
  475.         // Scale current position for new display area
  476.         if( wOldMax > 0 )
  477.             pPictureData->spmsHScroll.wCurPos =
  478.             MulDiv( pPictureData->spmsHScroll.wCurPos,
  479.             pPictureData->spmsHScroll.wCurMax, wOldMax );
  480.         else
  481.             pPictureData->spmsHScroll.wCurPos = 0;
  482.  
  483.         EnableWindow( pPictureData->spmsHScroll.hwnd, TRUE );
  484.  
  485.         SetScrollRange( pPictureData->spmsHScroll.hwnd, SB_CTL,
  486.             0, pPictureData->spmsHScroll.wCurMax, FALSE );
  487.         SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
  488.             pPictureData->spmsHScroll.wCurPos, TRUE );
  489.     }
  490.  
  491.     // Set vertical scrollbar parms
  492.     if( wDisplayHeight >= wCurPictHeight ) {
  493.         pPictureData->spmsVScroll.wCurPos  = 0;
  494.         pPictureData->spmsVScroll.wCurMax  = 0;
  495.         EnableWindow( pPictureData->spmsVScroll.hwnd, FALSE );
  496.     }
  497.     else {
  498.         wOldMax = pPictureData->spmsVScroll.wCurMax;
  499.         pPictureData->spmsVScroll.wCurMax =
  500.             wCurPictHeight - wDisplayHeight;
  501.         // Scale current position for new display area
  502.         if( wOldMax > 0 )
  503.             pPictureData->spmsVScroll.wCurPos =
  504.             MulDiv( pPictureData->spmsVScroll.wCurPos,
  505.             pPictureData->spmsVScroll.wCurMax, wOldMax );
  506.         else
  507.             pPictureData->spmsVScroll.wCurPos = 0;
  508.  
  509.         EnableWindow( pPictureData->spmsVScroll.hwnd, TRUE );
  510.  
  511.         SetScrollRange( pPictureData->spmsVScroll.hwnd, SB_CTL,
  512.             0, pPictureData->spmsVScroll.wCurMax, FALSE );
  513.         SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
  514.             pPictureData->spmsVScroll.wCurPos, TRUE );
  515.     }
  516.  
  517.  
  518.     // Define ->rcCurPictureRect.   The point (0, 0) is always the Upper-Left
  519.     // corner of the display area. Therefore, rcCur.. .left and .top are
  520.     // negative if the picture is scrolled.
  521.     pPictureData->rcCurPictureRect.left =
  522.         - ((int) pPictureData->spmsHScroll.wCurPos);
  523.     pPictureData->rcCurPictureRect.top  =
  524.         - ((int) pPictureData->spmsVScroll.wCurPos);
  525.     pPictureData->rcCurPictureRect.right =
  526.         pPictureData->rcCurPictureRect.left + wCurPictWidth;
  527.     pPictureData->rcCurPictureRect.bottom =
  528.         pPictureData->rcCurPictureRect.top  + wCurPictHeight;
  529.  
  530.     return;
  531. }
  532.  
  533.  
  534. // Function: ProcessHorzScroll - Process horizontal scroll bar messages
  535. // --------------------------------------------------------------------
  536. // Parameters: HWND    hwndPicture       Handle of picture window
  537. //             WORD    wScrollCode       Scroll code as defined in windows.h
  538. //             int     nCurBoxPos        Current position of scroll box
  539. //
  540. // Returns:    LONG    0L if OK
  541. // --------------------------------------------------------------------
  542. LONG FAR ProcessHorzScroll
  543.     (HWND hwndPicture, WORD wScrollCode, int nCurBoxPos )
  544.  
  545. {
  546.     NPPICTUREDATA   pPictureData; // -> picture data struct
  547.     int             nPosition;    // Temp scroll position
  548.     WORD            wWidth;       // Picture width
  549.     int             nToScroll;    // Amount to scroll
  550.     RECT            rcPictArea;   // Picture rect in client coordinates
  551.  
  552.  
  553.     if( !(pPictureData =
  554.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  555.         CommonTellUser( ViewerQueryResources(),
  556.             VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  557.         return VIEWER_STRING_NOPICDATA;
  558.     }
  559.  
  560.     if( !IsWindowEnabled( pPictureData->spmsHScroll.hwnd ))
  561.         return 0L;
  562.  
  563.     nPosition = pPictureData->spmsHScroll.wCurPos;
  564.  
  565.     switch( wScrollCode ) {
  566.         case SB_PAGERIGHT:
  567.             nPosition += pPictureData->spmsHScroll.wCurPage;
  568.             break;
  569.         case SB_LINERIGHT:
  570.             nPosition += pPictureData->spmsHScroll.wCurLine;
  571.             break;
  572.         case SB_PAGELEFT:
  573.             nPosition -= pPictureData->spmsHScroll.wCurPage;
  574.             break;
  575.         case SB_LINELEFT:
  576.             nPosition -= pPictureData->spmsHScroll.wCurLine;
  577.             break;
  578.         case SB_LEFT:
  579.             nPosition = 0;
  580.             break;
  581.         case SB_RIGHT:
  582.             nPosition = pPictureData->spmsHScroll.wCurMax;
  583.             break;
  584.         case SB_THUMBPOSITION:
  585.             nPosition = (WORD) nCurBoxPos;
  586.             break;
  587.         default:
  588.             break;
  589.     }
  590.  
  591.     nPosition = min( max( 0, nPosition ),
  592.         (int) pPictureData->spmsHScroll.wCurMax );
  593.     if( nPosition != (int) pPictureData->spmsHScroll.wCurPos ) {
  594.         nToScroll = nPosition - pPictureData->spmsHScroll.wCurPos;
  595.         pPictureData->spmsHScroll.wCurPos = nPosition;
  596.  
  597.         wWidth = pPictureData->rcCurPictureRect.right -
  598.             pPictureData->rcCurPictureRect.left;
  599.         pPictureData->rcCurPictureRect.left  = -nPosition;
  600.         pPictureData->rcCurPictureRect.right = -nPosition + wWidth;
  601.  
  602.         SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
  603.             pPictureData->spmsHScroll.wCurPos, TRUE );
  604.  
  605.         // Get picture rect in picture coordinates
  606.         GetClientRect( hwndPicture, &rcPictArea );
  607.         PictureRectFromClient( &rcPictArea);
  608.         // Convert to client coordinates for ScrollWindow
  609.         PictureToClient( (LPPOINT) &rcPictArea, 2 );
  610.  
  611.         if( ((WORD) abs( nToScroll )) <
  612.             pPictureData->spmsHScroll.wCurPage ) {
  613.             UpdateWindow( hwndPicture );
  614.             ScrollWindow( hwndPicture, -nToScroll, 0,
  615.                 &rcPictArea, &rcPictArea );
  616.         }
  617.         else
  618.             InvalidateRect( hwndPicture, &rcPictArea, TRUE );
  619.  
  620.         UpdateWindow( hwndPicture );
  621.     }
  622.  
  623.     return 0L;
  624. }
  625.  
  626.  
  627. // Function: ProcessVertScroll - Process vertical scroll bar messages
  628. // --------------------------------------------------------------------
  629. // Parameters: HWND    hwndPicture       Handle of picture window
  630. //             WORD    wScrollCode       Scroll code as defined in windows.h
  631. //             int     nCurBoxPos        Current position of scroll box
  632. //
  633. // Returns:    LONG    0L if OK
  634. // --------------------------------------------------------------------
  635. LONG FAR ProcessVertScroll
  636.     (HWND hwndPicture, WORD wScrollCode, int nCurBoxPos )
  637.  
  638. {
  639.     NPPICTUREDATA   pPictureData; // -> picture data struct
  640.     int             nPosition;    // Temp scroll position
  641.     WORD            wHeight;      // Picture height
  642.     int             nToScroll;    // Amount to scroll
  643.     RECT            rcPictArea;   // Picture rect in client coordinates
  644.  
  645.     if( !(pPictureData =
  646.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  647.         CommonTellUser( ViewerQueryResources(),
  648.             VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  649.         return VIEWER_STRING_NOPICDATA;
  650.     }
  651.  
  652.     if( !IsWindowEnabled( pPictureData->spmsVScroll.hwnd ))
  653.         return 0L;
  654.  
  655.     nPosition = pPictureData->spmsVScroll.wCurPos;
  656.  
  657.     switch( wScrollCode ) {
  658.         case SB_PAGEDOWN:
  659.             nPosition += pPictureData->spmsVScroll.wCurPage;
  660.             break;
  661.         case SB_LINEDOWN:
  662.             nPosition += pPictureData->spmsVScroll.wCurLine;
  663.             break;
  664.         case SB_PAGEUP:
  665.             nPosition -= pPictureData->spmsVScroll.wCurPage;
  666.             break;
  667.         case SB_LINEUP:
  668.             nPosition -= pPictureData->spmsVScroll.wCurLine;
  669.             break;
  670.         case SB_TOP:
  671.             nPosition = 0;
  672.             break;
  673.         case SB_BOTTOM:
  674.             nPosition = pPictureData->spmsVScroll.wCurMax;
  675.             break;
  676.         case SB_THUMBPOSITION:
  677.             nPosition = nCurBoxPos;
  678.             break;
  679.         default:
  680.             break;
  681.     }
  682.  
  683.     nPosition = min( max( 0, nPosition ),
  684.         (int) pPictureData->spmsVScroll.wCurMax );
  685.     if( nPosition != (int) pPictureData->spmsVScroll.wCurPos ) {
  686.         nToScroll = nPosition - pPictureData->spmsVScroll.wCurPos;
  687.         pPictureData->spmsVScroll.wCurPos = nPosition;
  688.  
  689.         wHeight = pPictureData->rcCurPictureRect.bottom -
  690.             pPictureData->rcCurPictureRect.top;
  691.         pPictureData->rcCurPictureRect.top    = -nPosition;
  692.         pPictureData->rcCurPictureRect.bottom = -nPosition + wHeight;
  693.  
  694.         SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
  695.             pPictureData->spmsVScroll.wCurPos, TRUE );
  696.  
  697.         // Get picture rect in picture coordinates
  698.         GetClientRect( hwndPicture, &rcPictArea );
  699.         PictureRectFromClient( &rcPictArea);
  700.         // Convert to client coordinates for ScrollWindow
  701.         PictureToClient( (LPPOINT) &rcPictArea, 2 );
  702.  
  703.         if( ((WORD) abs( nToScroll )) <
  704.             pPictureData->spmsVScroll.wCurPage ) {
  705.             UpdateWindow( hwndPicture );
  706.             ScrollWindow( hwndPicture, 0, -nToScroll,
  707.                 &rcPictArea, &rcPictArea );
  708.         }
  709.         else
  710.             InvalidateRect( hwndPicture, &rcPictArea, TRUE );
  711.  
  712.         UpdateWindow( hwndPicture );
  713.     }
  714.  
  715.     return 0L;
  716. }
  717.  
  718. // Function: ScrollToCorner - Scroll to upper_left or lower-right corner
  719. // --------------------------------------------------------------------
  720. // Parameters: HWND    hwndPicture       Handle of picture window
  721. //             WORD    wScrollCode       Scroll code as defined in windows.h
  722. //
  723. // Returns:    LONG    0L if OK
  724. // --------------------------------------------------------------------
  725. LONG FAR ScrollToCorner(HWND hwndPicture, WORD vk_key )
  726.  
  727. {
  728.     NPPICTUREDATA   pPictureData;  // -> picture data struct
  729.     int             nHorzPosition; // Temp horz scroll position
  730.     int             nVertPosition; // Temp vert scroll position
  731.     WORD            wWidth;        // Picture width
  732.     WORD            wHeight;       // Picture height
  733.     int             nHorzToScroll; // Amount to scroll horz
  734.     int             nVertToScroll; // Amount to scroll vert
  735.     RECT            rcPictArea;    // Picture rect in client coordinates
  736.  
  737.     if( !(pPictureData =
  738.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  739.         CommonTellUser( ViewerQueryResources(),
  740.             VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  741.         return VIEWER_STRING_NOPICDATA;
  742.     }
  743.  
  744.     if( vk_key == VK_HOME )
  745.         nVertPosition = nHorzPosition = 0;
  746.     else {
  747.         nHorzPosition = pPictureData->spmsHScroll.wCurMax;          
  748.         nVertPosition = pPictureData->spmsVScroll.wCurMax;          
  749.     }
  750.  
  751.     nHorzToScroll = nHorzPosition - (int) pPictureData->spmsHScroll.wCurPos;
  752.     nVertToScroll = nVertPosition - (int) pPictureData->spmsVScroll.wCurPos;
  753.     if( nHorzToScroll || nVertToScroll ) {
  754.         pPictureData->spmsHScroll.wCurPos = nHorzPosition;
  755.         pPictureData->spmsVScroll.wCurPos = nVertPosition;
  756.  
  757.         wWidth = pPictureData->rcCurPictureRect.right -
  758.             pPictureData->rcCurPictureRect.left;
  759.         pPictureData->rcCurPictureRect.left  = -nHorzPosition;
  760.         pPictureData->rcCurPictureRect.right = -nHorzPosition + wWidth;
  761.  
  762.         wHeight = pPictureData->rcCurPictureRect.bottom -
  763.             pPictureData->rcCurPictureRect.top;
  764.         pPictureData->rcCurPictureRect.top    = -nVertPosition;
  765.         pPictureData->rcCurPictureRect.bottom = -nVertPosition + wHeight;
  766.  
  767.         if( IsWindowEnabled( pPictureData->spmsHScroll.hwnd ))
  768.             SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
  769.             pPictureData->spmsHScroll.wCurPos, TRUE );
  770.         if( IsWindowEnabled( pPictureData->spmsVScroll.hwnd ))
  771.             SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
  772.             pPictureData->spmsVScroll.wCurPos, TRUE );
  773.  
  774.         // Get picture rect in picture coordinates
  775.         GetClientRect( hwndPicture, &rcPictArea );
  776.         PictureRectFromClient( &rcPictArea);
  777.         // Convert to client coordinates for ScrollWindow
  778.         PictureToClient( (LPPOINT) &rcPictArea, 2 );
  779.  
  780.         if( (((WORD) abs( nHorzToScroll )) <
  781.             pPictureData->spmsHScroll.wCurPage ) &&
  782.             (((WORD) abs( nVertToScroll )) <
  783.             pPictureData->spmsVScroll.wCurPage ))
  784.  
  785.         {
  786.             UpdateWindow( hwndPicture );
  787.             ScrollWindow( hwndPicture, -nHorzToScroll, -nVertToScroll,
  788.                 &rcPictArea, &rcPictArea );
  789.         }
  790.         else
  791.             InvalidateRect( hwndPicture, &rcPictArea, TRUE );
  792.  
  793.         UpdateWindow( hwndPicture );
  794.     }
  795.  
  796.     return 0L;
  797.  
  798. }
  799.  
  800.  
  801. // Function: IsInGrowBox - Determines if the cursor is in the grow box
  802. // --------------------------------------------------------------------
  803. // Parameters: HWND         hwndPicture       Handle of picture wnd
  804. //             POINT        ptCursor          Cursor position in client coords.
  805. //
  806. // Returns:    BOOL         TRUE if in grow box, else FALSE
  807. // --------------------------------------------------------------------
  808. BOOL FAR IsInGrowBox( HWND hwndPicture, POINT ptCursor )
  809.  
  810. {
  811.     NPPICTUREDATA   pPictureData; // -> picture data struct
  812.  
  813.     if( !(pPictureData =
  814.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) ||
  815.         !PtInRect( &pPictureData->rcGrowBox, ptCursor ))
  816.         return FALSE;
  817.     else
  818.         return TRUE;
  819. }
  820.  
  821.  
  822. // Function: DestroyGrowBoxBitmap - Destroys the grow box bitnmap
  823. // --------------------------------------------------------------------
  824. // Parameters: VOID
  825. //
  826. // Returns:    VOID   
  827. // --------------------------------------------------------------------
  828. VOID FAR DestroyGrowBoxBitmap( VOID )
  829.  
  830. {
  831.     if( g.hbmpGrowBox ) {
  832.         DeleteObject( g.hbmpGrowBox );
  833.         g.hbmpGrowBox = NULL;
  834.     }
  835.  
  836.     return;
  837. }
  838.  
  839.  
  840. // Function: PaintTheGrowBox - Paints the grow box
  841. // --------------------------------------------------------------------
  842. // Parameters: HWND             hwndPicture     Handle of picture window
  843. //             HDC              hdc             DC of picture window
  844. //             NPPICTUREDATA    pPictureData    -> picture wnd data struct
  845. //
  846. // Returns:    VOID   
  847. // --------------------------------------------------------------------
  848. VOID FAR PaintTheGrowBox( HWND hwndPicture,
  849.     HDC hdc, NPPICTUREDATA pPictureData )
  850.  
  851. {
  852.     HDC        hmemDC;     // Memory dc
  853.     HBITMAP    hbmpSave;   // Prev bitmap
  854.     HBRUSH     hbrushSave; // Background brush
  855.  
  856.     if( !g.hbmpGrowBox && 
  857.         !(g.hbmpGrowBox = GetGrowBoxBitmap( hdc, pPictureData )))
  858.         return;
  859.  
  860.     if( IsZoomed( hwndPicture ) && IsZoomed( ViewerQueryFrameWindow())) {
  861.         if( hbrushSave = SelectObject( hdc, GetStockObject( LTGRAY_BRUSH ))) {
  862.             PatBlt( hdc,
  863.                 pPictureData->rcGrowBox.left,
  864.                 pPictureData->rcGrowBox.top,
  865.                 pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left,
  866.                 pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top,
  867.                 PATCOPY );
  868.  
  869.             SelectObject( hdc, hbrushSave );
  870.         }
  871.     }
  872.     else {
  873.         hmemDC = NULL;
  874.         if( ( hmemDC = CreateCompatibleDC( hdc )) &&
  875.             ( hbmpSave = SelectObject( hmemDC, g.hbmpGrowBox ))) {
  876.             BitBlt( hdc, 
  877.                 pPictureData->rcGrowBox.left,
  878.                 pPictureData->rcGrowBox.top,
  879.                 pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left,
  880.                 pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top,
  881.                 hmemDC, 0, 0, SRCCOPY );
  882.  
  883.             SelectObject( hmemDC, hbmpSave );
  884.         }
  885.  
  886.         if( hmemDC )
  887.             DeleteDC( hmemDC );
  888.     }
  889.  
  890.     return;
  891. }
  892.  
  893.  
  894. // Function: GetGrowBoxBitmap - Create the grow box mem bitmap. This routine
  895. //                              saves a bitmap of the correct size so that
  896. //                              bitblt can be used to draw the bitmap instead
  897. //                              stetchblt which is much slower
  898. // --------------------------------------------------------------------
  899. // Parameters: HDC              hdc             DC of picture window
  900. //             NPPICTUREDATA    pPictureData    -> picture wnd data struct
  901. //
  902. // Returns:    HBITMAP          hbmpGrowBox     Handle of grow box mem bitmap   
  903. // --------------------------------------------------------------------
  904. static HBITMAP NEAR GetGrowBoxBitmap( HDC hdc, NPPICTUREDATA pPictureData )
  905.  
  906. {
  907.     HDC               hmemDC1;     // Mem dc
  908.     HDC               hmemDC2;     // Mem dc
  909.     BITMAP            bm;          // bitmap struct
  910.     HBITMAP           hbmp;        // Handle of resource bitmap
  911.     HBITMAP           hbmpSave1;   // Prev bitmap
  912.     HBITMAP           hbmpSave2;   // Prev bitmap
  913.     HBITMAP           hbmpGrowBox; // Handle of grow box bitmap
  914.     int               nWidth;      // Width of final bitmap
  915.     int               nHeight;     // Height of final bitmap
  916.     HBRUSH            hbrushSave;  // Prev brush
  917.     int               xOffset;     // x bitmap offset
  918.     int               yOffset;     // y bitmap offset
  919.  
  920.  
  921.     if( !( hbmp = LoadBitmap( ViewerQueryResources(), 
  922.         MAKEINTRESOURCE( VIEWER_GROWBOX_BITMAP ))))
  923.         return NULL;
  924.  
  925.     hmemDC1 = hmemDC2 = NULL;
  926.     nWidth  = pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left;
  927.     nHeight = pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top;
  928.  
  929.     if( ( hmemDC1 = CreateCompatibleDC( hdc )) &&
  930.         ( hmemDC2 = CreateCompatibleDC( hdc )) &&
  931.         ( hbmpGrowBox = CreateCompatibleBitmap
  932.         ( hdc, nWidth, nHeight ))) {
  933.         hbmpSave1 = SelectObject( hmemDC1, hbmp ); 
  934.         hbmpSave2 = SelectObject( hmemDC2, hbmpGrowBox );
  935.  
  936.         // set the background to light gray
  937.         hbrushSave = SelectObject( hmemDC2, GetStockObject( LTGRAY_BRUSH ));
  938.         PatBlt( hmemDC2, 0, 0, nWidth, nHeight, PATCOPY );
  939.         SelectObject( hmemDC2, hbrushSave );
  940.  
  941.         GetObject( hbmp, sizeof( BITMAP ), &bm );
  942.         xOffset = ( nWidth - bm.bmWidth ) / 2;
  943.         yOffset = ( nHeight - bm.bmHeight ) / 2;
  944.  
  945.         BitBlt( hmemDC2, max( 0, xOffset ), max( 0, yOffset ),
  946.             min( bm.bmWidth, nWidth ),
  947.             min( bm.bmHeight, nHeight ),
  948.             hmemDC1, 
  949.             max( 0, -xOffset ),
  950.             max( 0, -yOffset ), SRCCOPY );
  951.  
  952.         SelectObject( hmemDC1, hbmpSave1 ); 
  953.         SelectObject( hmemDC2, hbmpSave2 );
  954.     }
  955.  
  956.     if( hmemDC1 )
  957.         DeleteDC( hmemDC1 );
  958.     if( hmemDC2 )
  959.         DeleteDC( hmemDC2 );
  960.  
  961.     DeleteObject( hbmp );
  962.  
  963.     return hbmpGrowBox;
  964. }
  965.  
  966.  
  967. // Function: LimitTheDragSize - Limits the resized of the window so that it stays 
  968. //                              inside the MDI client rect. Used with grow box
  969. //                              processing
  970. // --------------------------------------------------------------------
  971. // Parameters: HWND             hwndPicture     hwnd of picture window
  972. //             BOOL             bDragging       TRUE if dragging using grow box
  973. //
  974. // Returns:    VOID   
  975. // --------------------------------------------------------------------
  976. VOID FAR LimitTheDragSize( HWND hwndPicture, BOOL bDragging )
  977.  
  978. {
  979.     RECT   rcClient;     // Client rect of MDI client
  980.     RECT   rcwndPicture; // Window rect of picture wnd
  981.  
  982.     if( !( g.bLimitGrowBoxResize = bDragging ))
  983.         return;
  984.  
  985.     if( !IsZoomed( hwndPicture )) {
  986.         GetWindowRect( hwndPicture, &rcwndPicture );
  987.         GetClientRect( ViewerQueryClientWindow(), &rcClient );
  988.  
  989.         MapWindowPoints( HWND_DESKTOP, ViewerQueryClientWindow(), 
  990.             (LPPOINT) &rcwndPicture, 2 );
  991.  
  992.         g.ptMaxGrowBoxResize.x = rcClient.right - rcwndPicture.left;
  993.         g.ptMaxGrowBoxResize.y = rcClient.bottom - rcwndPicture.top;
  994.     }
  995.  
  996.     return;
  997. }
  998.  
  999.  
  1000. // Function: InitMaxWndGrowBoxResize - Initializes the maximized window grow
  1001. //                                     box resizing
  1002. // --------------------------------------------------------------------
  1003. // Parameters: HWND        hwndPicture    Handle of picture wnd
  1004. //             POINT       ptCursor       Position of cursor
  1005. //
  1006. // Returns:    BOOL        TRUE if successful
  1007. // --------------------------------------------------------------------
  1008. BOOL FAR InitMaxWndGrowBoxResize( HWND hwndPicture, POINT ptCursor )
  1009.  
  1010. {
  1011.     RECT         rcClipCursor; // Clip cursor rect
  1012.     HDC          hdc;          // DC of desktop
  1013.  
  1014.  
  1015.     GetWindowRect( ViewerQueryFrameWindow(), &g.rcResizeRect );
  1016.     ClientToScreen( hwndPicture, &ptCursor );
  1017.     g.ptCursorOffset.x = g.rcResizeRect.right  - ptCursor.x;
  1018.     g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  1019.  
  1020.     rcClipCursor.left = g.rcResizeRect.left + 
  1021.         GetSystemMetrics( SM_CXMINTRACK ) - g.ptCursorOffset.x;
  1022.     rcClipCursor.top  = g.rcResizeRect.top +
  1023.         GetSystemMetrics( SM_CYMINTRACK ) - g.ptCursorOffset.y;
  1024.  
  1025.     if( hdc = GetDC( NULL )) {
  1026.         rcClipCursor.right =
  1027.             GetDeviceCaps( hdc, HORZRES ) - g.ptCursorOffset.x;
  1028.         rcClipCursor.bottom = 
  1029.             GetDeviceCaps( hdc, VERTRES ) - g.ptCursorOffset.y;
  1030.         ReleaseDC( NULL, hdc );
  1031.     }
  1032.     else {
  1033.         rcClipCursor.right  = 0x7fff;
  1034.         rcClipCursor.bottom = 0x7fff;
  1035.     }
  1036.     ClipCursor( &rcClipCursor );
  1037.  
  1038.     DrawTheFrameRect( &g.rcResizeRect );
  1039.  
  1040.     return TRUE;
  1041. }
  1042.  
  1043.  
  1044. // Function: MoveTheFrameRect - Moves the resizing rect during maximized 
  1045. //                              window grow box resizing
  1046. // --------------------------------------------------------------------
  1047. // Parameters: HWND        hwndPicture    Handle of picture wnd
  1048. //             POINT       ptCursor       Position of cursor
  1049. //
  1050. // Returns:    VOID
  1051. // --------------------------------------------------------------------
  1052. VOID FAR MoveTheFrameRect( HWND hwndPicture, POINT ptCursor )
  1053.  
  1054. {
  1055.     DrawTheFrameRect( &g.rcResizeRect );
  1056.  
  1057.     ClientToScreen( hwndPicture, &ptCursor );
  1058.     g.rcResizeRect.right  = ptCursor.x + g.ptCursorOffset.x;
  1059.     g.rcResizeRect.bottom = ptCursor.y + g.ptCursorOffset.y;
  1060.  
  1061.     DrawTheFrameRect( &g.rcResizeRect );
  1062.  
  1063.     return;
  1064. }
  1065.  
  1066.  
  1067. // Function: EndMaxWndGrowBoxResize - Terminates the maximized window grow
  1068. //                                    box resizing
  1069. // --------------------------------------------------------------------
  1070. // Parameters: HWND        hwndPicture    Handle of picture wnd
  1071. //
  1072. // Returns:    VOID
  1073. // --------------------------------------------------------------------
  1074. VOID FAR EndMaxWndGrowBoxResize( HWND hwndPicture )
  1075.  
  1076. {
  1077.     DrawTheFrameRect( &g.rcResizeRect );
  1078.     DrawTheFrameRect( NULL ); // Does clean up
  1079.  
  1080.     ClipCursor( NULL );
  1081.     MoveWindow( ViewerQueryFrameWindow(),
  1082.         g.rcResizeRect.left, g.rcResizeRect.top,
  1083.         g.rcResizeRect.right - g.rcResizeRect.left,
  1084.         g.rcResizeRect.bottom - g.rcResizeRect.top, TRUE );
  1085.  
  1086.     return;
  1087. }
  1088.  
  1089.  
  1090. // Function: DrawTheFrameRect - Draws the resizing frame
  1091. // --------------------------------------------------------------------
  1092. // Parameters: RECT      lprcResizeRect     -> resize rect
  1093. //
  1094. // Returns:    VOID 
  1095. // --------------------------------------------------------------------
  1096. static VOID NEAR DrawTheFrameRect( LPRECT lprcResizeRect )
  1097.  
  1098. {
  1099.     HDC            hdc;             // DC of desktop
  1100.     HBRUSH         hbrushSave;      // Prev brush
  1101.     HBITMAP        hbitmapCheckers; // Handle of checkerboard bitmap
  1102.  
  1103.     typedef  BOOL ( CALLBACK* FFRAMEPROC ) (HDC, LPRECT, int, int, DWORD);
  1104.  
  1105.     static  WORD   wBorderWidth;             // Width of vertical resize border
  1106.     static  WORD   wBorderHeight;            // Height of horizontal resize border
  1107.     static  FFRAMEPROC  lpfnFastWindowFrame; // -> FastWindowFrame()
  1108.     static  HBRUSH  hbrushCheckers;          // Handle to frame brush
  1109.  
  1110.  
  1111.     // FastWindowFrame() is an undocumented Windows function
  1112.     // described in "Undocumented Windows" by Andrew Schulman,
  1113.     // David Maxey and Matt Pietrek, Addison Wesley, 1992.
  1114.  
  1115.     if( lprcResizeRect == NULL ) // Clean up 
  1116.     {
  1117.         if( hbrushCheckers ) {
  1118.             DeleteObject( hbrushCheckers );
  1119.             hbrushCheckers = NULL;
  1120.         }
  1121.         return;
  1122.     }
  1123.  
  1124.     if( !lpfnFastWindowFrame ) {
  1125.         lpfnFastWindowFrame = (FFRAMEPROC) GetProcAddress( 
  1126.             GetModuleHandle( "GDI" ), "FASTWINDOWFRAME" );
  1127.         wBorderWidth  = GetSystemMetrics( SM_CXFRAME ) - 1;
  1128.         wBorderHeight = GetSystemMetrics( SM_CXFRAME ) - 1;
  1129.     }
  1130.  
  1131.     if( !hbrushCheckers &&
  1132.         ( hbitmapCheckers = LoadBitmap( ViewerQueryInstance(),
  1133.         MAKEINTRESOURCE( VIEWER_CHECKERS_BITMAP )))) {
  1134.         hbrushCheckers = CreatePatternBrush( hbitmapCheckers );
  1135.         DeleteObject( hbitmapCheckers );
  1136.     }
  1137.  
  1138.     if( hdc = GetDC( NULL )) {
  1139.         if( lpfnFastWindowFrame ) {
  1140.             if( hbrushCheckers )
  1141.                 hbrushSave = SelectObject( hdc, hbrushCheckers );
  1142.             else
  1143.                 hbrushSave = SelectObject( hdc,
  1144.                 GetStockObject( GRAY_BRUSH ));
  1145.  
  1146.             if( !( *lpfnFastWindowFrame ) ( hdc, lprcResizeRect, 
  1147.                 wBorderWidth, wBorderHeight, PATINVERT )) { // Use PatBlt when FastWindowFrame fails
  1148.                 ExcludeClipRect( hdc,
  1149.                     lprcResizeRect->left + wBorderWidth,
  1150.                     lprcResizeRect->top  + wBorderHeight,
  1151.                     lprcResizeRect->right  - wBorderWidth,
  1152.                     lprcResizeRect->bottom - wBorderHeight );
  1153.  
  1154.                 PatBlt( hdc, lprcResizeRect->left,
  1155.                     lprcResizeRect->top,
  1156.                     lprcResizeRect->right - lprcResizeRect->left,
  1157.                     lprcResizeRect->bottom - lprcResizeRect->top,
  1158.                     PATINVERT );
  1159.             }
  1160.  
  1161.             if( hbrushSave )
  1162.                 SelectObject( hdc, hbrushSave );
  1163.         }
  1164.         else {
  1165.             DrawFocusRect( hdc, lprcResizeRect ); 
  1166.         }
  1167.  
  1168.         ReleaseDC( NULL, hdc );
  1169.     }
  1170.  
  1171.     return;
  1172. }
  1173.  
  1174.  
  1175. // Function: PictureBannerWndProc - Window proc for the banner child window
  1176. // --------------------------------------------------------------------
  1177. // Parameters: As required by Microsoft Windows
  1178. //
  1179. // Returns:    Via DefWindowProc
  1180. // --------------------------------------------------------------------
  1181. LONG __export CALLBACK PictureBannerWndProc
  1182.     (HWND hwndBanner, UINT message, WPARAM wParam, LPARAM lParam)
  1183.  
  1184. {
  1185.     NPPICTUREDATA  pPictureData; // -> picture data struct
  1186.     PAINTSTRUCT    ps;           // Paint struct
  1187.     RECT           rcClient;     // Client rect of control
  1188.     UINT           nSaveAlign;   // Prev text align
  1189.     WORD           wBaseLine;    // Base line for text output
  1190.     HFONT          hFont;        // Handle of font
  1191.     HFONT          hsaveFont;    // Handle of prev font
  1192.     int            nHeight;      // Height of font
  1193.  
  1194.  
  1195.     if( message == WM_PAINT ) {
  1196.         if( !(pPictureData = (NPPICTUREDATA) GetWindowWord
  1197.             ( GetParent( hwndBanner ), 0 )))
  1198.             return 0L;
  1199.  
  1200.         if( !BeginPaint( hwndBanner, &ps ))
  1201.             return 0L;
  1202.  
  1203.         GetClientRect( hwndBanner, &rcClient );
  1204.         MoveTo( ps.hdc, 0, rcClient.bottom - 1 );
  1205.         LineTo( ps.hdc, rcClient.right, rcClient.bottom - 1 );
  1206.  
  1207.         // Don't report an error if this fails since it will just
  1208.         // use the system font instead
  1209.         nHeight = -MulDiv( BANNER_TEXT_HEIGHT,
  1210.             GetDeviceCaps( ps.hdc, LOGPIXELSY ), 72 );
  1211.         hsaveFont = NULL;
  1212.         if( hFont = MakeAnArialFont( ps.hdc, nHeight ))
  1213.             hsaveFont = SelectObject( ps.hdc, hFont );
  1214.  
  1215.         wBaseLine = 3 * rcClient.bottom / 4;
  1216.         nSaveAlign = SetTextAlign( ps.hdc, TA_LEFT | TA_BASELINE );
  1217.         TextOut( ps.hdc, 6, wBaseLine, pPictureData->szPictType,
  1218.             lstrlen( pPictureData->szPictType ));
  1219.  
  1220.         SetTextAlign( ps.hdc, TA_RIGHT | TA_BASELINE );
  1221.         SetTextCharacterExtra( ps.hdc, 
  1222.             GetTextCharacterExtra( ps.hdc ) + TEXT_EXTRA_SPACING );
  1223.  
  1224.         TextOut( ps.hdc, rcClient.right - 6, wBaseLine,
  1225.             pPictureData->szFileSize,
  1226.             lstrlen( pPictureData->szFileSize ));
  1227.  
  1228.         SetTextAlign( ps.hdc, nSaveAlign );
  1229.  
  1230.         if( hsaveFont )
  1231.             SelectObject( ps.hdc, hsaveFont ); 
  1232.         if( hFont )
  1233.             DeleteObject( hFont ); 
  1234.  
  1235.         EndPaint( hwndBanner, &ps );
  1236.         return 0L;
  1237.     }
  1238.     else
  1239.         return DefWindowProc( hwndBanner, message, wParam, lParam);
  1240. }
  1241.  
  1242.  
  1243. // Function: MakeAnArialFont - Creates a logical font
  1244. // --------------------------------------------------------------------
  1245. // Parameters: HDC           hdc              Device context
  1246. //             int           nTextSize        Size of font
  1247. //
  1248. // Returns:    HFONT         hFont
  1249. //           Note: It is up to the caller to eventually delete this font
  1250. // --------------------------------------------------------------------
  1251. HFONT FAR MakeAnArialFont( HDC hdc, int nTextSize )
  1252.  
  1253. {
  1254.     HFONT       hFont; // Handle to created font
  1255.     PLOGFONT    plf;   // -> to font struct
  1256.  
  1257.     if( !( plf = (PLOGFONT) LocalAlloc( LPTR, sizeof( LOGFONT ))))
  1258.         return NULL;
  1259.  
  1260.     plf->lfHeight         = nTextSize;
  1261.     plf->lfWeight         = FW_LIGHT;
  1262.     plf->lfOutPrecision   = OUT_TT_ONLY_PRECIS;
  1263.     plf->lfPitchAndFamily = FF_SWISS;
  1264.     LoadString( ViewerQueryResources(), VIEWER_STRING_FACENAME, 
  1265.         plf->lfFaceName, sizeof( plf->lfFaceName ));
  1266.  
  1267.     hFont = CreateFontIndirect( plf );
  1268.  
  1269.     LocalFree( (LOCALHANDLE) plf );
  1270.  
  1271.     return hFont;
  1272. }
  1273.  
  1274.  
  1275. // Function: RegisterChildControls - Registers the window classes for the
  1276. //                                   picture resizing and banner child windows
  1277. // --------------------------------------------------------------------
  1278. // Parameters: HINSTANCE     hInstance  Instance of application
  1279. //
  1280. // Returns:    BOOL          TRUE if OK
  1281. // --------------------------------------------------------------------
  1282. BOOL FAR RegisterChildControls( HINSTANCE hInstance )
  1283.  
  1284. {
  1285.     WNDCLASS     wc; // Window class information
  1286.  
  1287.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  1288.     wc.lpfnWndProc   = PictureZoomWndProc;
  1289.     wc.cbClsExtra    = 0;
  1290.     wc.cbWndExtra    = 0;
  1291.     wc.hInstance     = hInstance;
  1292.     wc.hIcon         = NULL;
  1293.     wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  1294.     wc.hbrBackground = (HBRUSH) ( COLOR_BTNFACE + 1 );
  1295.     wc.lpszMenuName  = NULL;
  1296.     wc.lpszClassName = PICTURE_ZOOM_CLASS;
  1297.  
  1298.     if( !RegisterClass( &wc ))
  1299.         return FALSE;
  1300.  
  1301.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  1302.     wc.lpfnWndProc   = PictureBannerWndProc;
  1303.     wc.cbClsExtra    = 0;
  1304.     wc.cbWndExtra    = 0;
  1305.     wc.hInstance     = hInstance;
  1306.     wc.hIcon         = NULL;
  1307.     wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  1308.     wc.hbrBackground = GetStockObject( WHITE_BRUSH );
  1309.     wc.lpszMenuName  = NULL;
  1310.     wc.lpszClassName = PICTURE_BANNER_CLASS;
  1311.  
  1312.     return RegisterClass( &wc );
  1313. }
  1314.